#include "App_IO.h"
#include "Dri_NVS.h"
#include "Inf_BDR6120.h"
#include "Dri_OTA.h"

// 创建句柄
extern TaskHandle_t xFingerprintHandle;
// 默认管理元KEY
#define ADMIN "admin"
// 默认3个user
#define USER_COUNT 3
// 用户总数KEY
#define USER_COUNT_KEY "user_count"

// 按键停止总时间
static uint16_t is_KEY_NO_Count = 0;

/**
 * @brief  获取按键数据
 *
 * @param key_array 按键数组
 */
Com_Status app_IO_Key_Click(char *key_array, uint8_t *array_len)
{
    is_KEY_NO_Count = 0;
    while (1)
    {
        // 获取键盘输入数据
        Touch_Key key = Inf_SC12B_GetKey();
        if (key == KEY_NO)
        {
            is_KEY_NO_Count++;
            if (is_KEY_NO_Count >= 100)
            {

                return Com_TIMEOUT;
            }
            vTaskDelay(50);
            continue;
        }

        // 处理按键声音以及灯光
        sayNum(key);
        // 添加LED效果
        // 关闭LED
        Inf_WS2812_LEDOff();
        // 开启
        Inf_WS2812_LEDOn(key, blue);
        // 获取到按键按下数据
        is_KEY_NO_Count = 0;
        if (key == KEY_M)
        {
            return Com_ERROR;
        }
        // 按# 则ok
        if (key == KEY_SHARP)
        {
            return Com_OK;
        }
        // 按其他存入数组中
        // 将数字转换为对应的字符
        key_array[(*array_len)++] = key + 48;
        vTaskDelay(50);
    }
    return Com_OTHER;
}

/**
 * @brief 处理值业务
 *
 * @param key_array 值数据
 * @param array_len 数组长度
 * @return Com_Status
 */
void App_IO_HandlerStr(char *str, uint8_t array_len)
{
    MY_LOGE("str:%s   len:%d", str, array_len);
    if (array_len < 2)
    {
        sayIllegalOperation();
        return;
    }
    // 输入命令
    if (array_len == 2)
    {
        if (str[0] == '0' && str[1] == '0') // 录入管理员
        {
            App_IO_AddAdmin(str);
        }
        else if (str[0] == '0' && str[1] == '1') // 删除管理员
        {
            App_IO_DelAdmin(str);
        }
        else if (str[0] == '1' && str[1] == '0') // 录入普通用户
        {
            MY_LOGE("录入普通用户");
            App_IO_AddUser();
        }
        else if (str[0] == '1' && str[1] == '1') // 删除普通用户
        {
            App_IO_DelUser();
        }
        else if (str[0] == '9' && str[1] == '9') // 删除所有密码
        {
            sayDelAll();
            App_IO_DelAll();
        }
        else if (str[0] == '2' && str[1] == '0') // 注册指纹`
        {
            sayWithoutInt();
            sayAddUserFingerprint();
            //  Com_Status com_status = App_IO_CheckAdmin();
            // if (com_status == Com_OK)
            // {
            //     // 通知指纹任务,注册
            //     xTaskNotify(fingerScanHandler, 1, eSetValueWithOverwrite);
            // }
            // else
            // {
            //     sayAddFail();
            // }
            // 通知指纹任务,注册 eSetValueWithOverwrite 覆盖
            xTaskNotify(xFingerprintHandle, 1, eSetValueWithOverwrite);
        }
        else if (str[0] == '2' && str[1] == '1') // 注册指纹`
        {
            sayWithoutInt();
            sayDelUserFingerprint();
            // 通知指纹任务,注册 eSetValueWithOverwrite 覆盖
            xTaskNotify(xFingerprintHandle, 2, eSetValueWithOverwrite);
        }
        else if (str[0] == '8' && str[1] == '8') // 注册指纹`
        {
            Dri_OTA_Init();
        }
        else
        {
            sayIllegalOperation();
        }
        return;
    }

    // 处理业务
    App_IO_CheckUser(str);
}

void App_IO_CheckUser(char *str)
{
    // 判断键盘输入的字符集是否在NVS中存在
    if (Dri_NVS_FindKey_Str(str) == ESP_OK)
    {
        sayWithoutInt();
        sayDoorBell();
        sayWithoutInt();
        sayDoorOpen();
        Inf_BDR6120_OpenLock();
    }
    else
    {
        sayWithoutInt();
        sayVerifyFail();
        sayWithoutInt();
        sayRetry();
    }
}

// 定义数组用于临时存放按键输入以及NVS读取的密码
// 第一次输入密码
char first_buffer[100] = {0};
uint8_t first_buffer_len = 0;
// 第二次输入密码
char second_buffer[100] = {0};
uint8_t second_buffer_len = 0;

/**
 * @brief 清空数据
 *
 */
static void App_IO_ClearBuffer(void)
{
    memset(first_buffer, 0, 100);
    memset(second_buffer, 0, 100);
    first_buffer_len = 0;
    second_buffer_len = 0;
}

/**
 * @brief  录入管理员
 *
 */
void App_IO_AddAdmin(char *str)
{
    // 判断是否存在admin, 存在则不能添加
    esp_err_t err = Dri_NVS_FindKey_Str(ADMIN);
    if (err == ESP_OK)
    {
        // 已经存在
        sayAdminFull();
        return;
    }

    // 没有则添加
    sayInputAdminPassword();
    // 获取键盘数据
    Com_Status com_status = app_IO_Key_Click(first_buffer, &first_buffer_len);
    // 判断状态 错误
    if (com_status == Com_ERROR)
    {
        sayIllegalOperation();
        App_IO_ClearBuffer();
        return;
    }
    // 输入超时
    if (com_status == Com_TIMEOUT)
    {
        App_IO_ClearBuffer();
        return;
    }
    // 输入正确
    if (com_status == Com_OK)
    {
        // 1.3 再次输入与上一次相同的数字组合
        sayInputAdminPasswordAgain();
        // 获取键盘数据
        com_status = app_IO_Key_Click(second_buffer, &second_buffer_len);
        // 判断状态 错误
        if (com_status == Com_ERROR)
        {
            sayIllegalOperation();
            App_IO_ClearBuffer();
            return;
        }
        // 输入超时
        if (com_status == Com_TIMEOUT)
        {
            App_IO_ClearBuffer();
            return;
        }
        MY_LOGE("first_buffer:%s   len:%d", first_buffer, first_buffer_len);
        MY_LOGE("second_buffer:%s   len:%d", second_buffer, second_buffer_len);
        // 判断是否一致,不一致
        if (strcmp(first_buffer, second_buffer) != 0)
        {
            MY_LOGE("不一致");
            sayAddFail();
            App_IO_ClearBuffer();
            return;
        }

        // 一致
        esp_err_t err = Dri_NVS_SetData_Str((char *)ADMIN, first_buffer);
        if (err == ESP_OK)
        {
            sayAddSucc();
        }
        else
        {
            sayAddFail();
        }
        App_IO_ClearBuffer();
        return;
    }
}

/**
 * @brief  删除管理员
 *
 */
void App_IO_DelAdmin(char *str)
{
    // 判断是否存在admin, 存在则不能添加
    esp_err_t err = Dri_NVS_FindKey_Str(ADMIN);
    if (err != ESP_OK)
    {
        sayInvalid();
        return;
    }

    // 存在则删除
    // 验证管理员
    sayWithoutInt();
    sayDelAdmin();
    Com_Status com_status = app_IO_Key_Click(first_buffer, &first_buffer_len);
    // 判断状态 错误
    if (com_status == Com_ERROR)
    {
        sayIllegalOperation();
        App_IO_ClearBuffer();
        return;
    }
    // 输入超时
    if (com_status == Com_TIMEOUT)
    {
        App_IO_ClearBuffer();
        return;
    }
    // 输入正确
    if (com_status == Com_OK)
    {
        // 获取管理员密码
        Dri_NVS_GetData_Str((char *)ADMIN, second_buffer, &second_buffer_len);
        if (strcmp(first_buffer, second_buffer) != 0)
        {
            MY_LOGE("不一致");
            sayDelFail();
            App_IO_ClearBuffer();
            return;
        }

        // 一致删除
        Dri_NVS_DelKey((char *)ADMIN);
        if (err == ESP_OK)
        {
            MY_LOGE("Success\r\n");
            sayDelSucc();
        }
        else
        {
            MY_LOGE("Fail 11111\r\n");
            sayDelFail();
        }
        App_IO_ClearBuffer();
        return;
    }
}

/**
 * @brief  录入普通用户
 *
 */
void App_IO_AddUser(void)
{
    // 判断是否存在admin, 存在则不能添加
    esp_err_t err = Dri_NVS_FindKey_Str(ADMIN);
    if (err != ESP_OK)
    {
        // 已经存在
        sayInvalid();
        return;
    }

    // 验证管理员
    sayWithoutInt();
    sayAddUser();
    Com_Status com_status = App_IO_CheckAdmin();
    // 判断状态 错误
    if (com_status == Com_ERROR)
    {
        sayIllegalOperation();
        App_IO_ClearBuffer();
        return;
    }
    // 输入超时
    if (com_status == Com_TIMEOUT)
    {
        App_IO_ClearBuffer();
        return;
    }

    // 成功
    sayInputUserPassword();
    com_status = app_IO_Key_Click(first_buffer, &first_buffer_len);
    if (com_status == Com_ERROR)
    {
        sayIllegalOperation();
        App_IO_ClearBuffer();
        return;
    }
    // 输入超时
    if (com_status == Com_TIMEOUT)
    {
        App_IO_ClearBuffer();
        return;
    }

    // 成功
    sayInputUserPasswordAgain();
    com_status = app_IO_Key_Click(second_buffer, &second_buffer_len);
    if (com_status == Com_ERROR)
    {
        sayIllegalOperation();
        App_IO_ClearBuffer();
        return;
    }
    // 输入超时
    if (com_status == Com_TIMEOUT)
    {
        App_IO_ClearBuffer();
        return;
    }

    // 输入两次数据不一致
    if (strcmp((char *)first_buffer, (char *)second_buffer) != 0)
    {
        sayAddFail();
        // 清空缓存
        App_IO_ClearBuffer();
        return;
    }

    // 数据一致
    // 判断添加次数
    com_status = App_IO_Add_User_Count(first_buffer);
    if (com_status == Com_ERROR)
    {
        // 清空缓存
        App_IO_ClearBuffer();
        return;
    }

    char *value = "1";
    esp_err_t err_t = Dri_NVS_SetData_Str(first_buffer, value);
    if (err_t == ESP_OK)
    {
        sayAddSucc();
    }
    else
    {
        sayAddFail();
    }
    App_IO_ClearBuffer();
    return;
}

/**
 * @brief  删除普通用户
 *
 */
void App_IO_DelUser(void)
{
    // 判断是否存在admin, 存在则不能添加
    esp_err_t err = Dri_NVS_FindKey_Str(ADMIN);
    if (err != ESP_OK)
    {
        // 已经存在
        sayInvalid();
        return;
    }

    // 验证管理员 TODO
    sayWithoutInt();
    sayDelUser();
    Com_Status com_status = App_IO_CheckAdmin();
    // 判断状态 错误
    if (com_status == Com_ERROR)
    {
        sayIllegalOperation();
        App_IO_ClearBuffer();
        return;
    }
    // 输入超时
    if (com_status == Com_TIMEOUT)
    {
        App_IO_ClearBuffer();
        return;
    }

    // 从键盘读取普通用户密码
    sayInputUserPassword();
    // 根据key,到flash中查询数据
    com_status = app_IO_Key_Click(first_buffer, &first_buffer_len);
    if (com_status == Com_ERROR)
    {
        sayIllegalOperation();
        App_IO_ClearBuffer();
        return;
    }
    // 输入超时
    if (com_status == Com_TIMEOUT)
    {
        App_IO_ClearBuffer();
        return;
    }
    int8_t num = 0;
    Dri_NVS_GetData_Int(USER_COUNT_KEY, &num);
    MY_LOGE("删除用户 num=%d", num);
    if (num == 0)
    {
        sayDelFail();
        App_IO_ClearBuffer();
        return;
    }
    if (num > 0)
    {
        num = num - 1;
        Dri_NVS_SetData_Int(USER_COUNT_KEY, num);
    }

    // 正确,根据key删除密码
    err = Dri_NVS_DelKey(first_buffer);
    if (err == ESP_OK)
    {
        sayDelSucc();
    }
    else
    {
        sayDelFail();
    }
    App_IO_ClearBuffer();
    return;
}

/**
 * @brief  删除所有密码
 *
 */
void App_IO_DelAll(void)
{
    Dri_NVS_DelAll();
}

/**
 * @brief 验证管理员
 *
 */
Com_Status App_IO_CheckAdmin(void)
{
    // 从键盘读取管理员密码
    sayWithoutInt();
    sayInputAdminPassword();
    // 获取键盘数据
    Com_Status com_status = app_IO_Key_Click(first_buffer, &first_buffer_len);
    // 判断状态 错误
    if (com_status == Com_ERROR)
    {
        MY_LOGE("admin 错误");
        sayIllegalOperation();
        App_IO_ClearBuffer();
        return Com_ERROR;
    }
    // 输入超时
    if (com_status == Com_TIMEOUT)
    {
        App_IO_ClearBuffer();
        return Com_TIMEOUT;
    }

    // 输入成功
    // 从NVS读取已经保存的管理员密码
    // 获取管理员密码
    esp_err_t err = Dri_NVS_GetData_Str((char *)ADMIN, second_buffer, &second_buffer_len);
    if (err != ESP_OK)
    {
        MY_LOGE("admin err != ESP_OK");
        App_IO_ClearBuffer();
        return Com_ERROR;
    }

    // 密码不一致
    if (strcmp(first_buffer, second_buffer) != 0)
    {
        MY_LOGE("不一致");
        sayDelFail();
        App_IO_ClearBuffer();
        return Com_ERROR;
    }

    // 密码一致
    App_IO_ClearBuffer();
    MY_LOGE("密码一致");
    return Com_OK;
}

/**
 * @brief 添加用户判断用户总数
 *
 * @param str
 */
Com_Status App_IO_Add_User_Count(char *str)
{
    // 查询用户密码是否存在
    esp_err_t err = Dri_NVS_FindKey_Str(str);
    // // 1. 存在则直接提示  return
    if (err == ESP_OK)
    {
        MY_LOGE("密码存在");
        sayWithoutInt();
        user_Repeat_PWD();
        return Com_ERROR;
    }

    //  查询是否存在count KEY
    int8_t num = 99;
    err = Dri_NVS_GetData_Int(USER_COUNT_KEY, &num);
    MY_LOGE("没有这个数据 %d", num);
    // 没有这个数据
    if (num == 99)
    {
        // 添加一下
        MY_LOGE("没有这个数据");
        Dri_NVS_SetData_Int(USER_COUNT_KEY, 1);
        return Com_OK;
    }

    // 判断数据是不是已经超过 >= 3
    if (num < USER_COUNT)
    {
        // 添加用户
        MY_LOGE("添加用户");
        Dri_NVS_SetData_Int(USER_COUNT_KEY, num + 1);
        return Com_OK;
    }
    else
    {
        // 用户已满
        MY_LOGE("用户已满");
        sayWithoutInt();
        sayUserFull();
        return Com_ERROR;
    }
}